package com.wujie.mall.infrastructure.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.InitializingBean;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 配置管理器 - 单例模式实现
 * 
 * 设计模式：Singleton Pattern（单例模式）
 * 应用场景：系统全局配置管理，确保配置的一致性和唯一性
 * 
 * 特点：
 * 1. 使用双重检查锁定确保线程安全
 * 2. 懒加载，只有在需要时才创建实例
 * 3. 提供全局访问点
 * 4. 集成Spring管理，同时支持传统单例访问
 * 
 * @author wujie
 * @since 2024-08-26
 */
@Slf4j
@Component
@ConfigurationProperties(prefix = "mall")
@Getter
@Setter
public class ConfigurationManager implements InitializingBean {

    /**
     * 单例实例，使用volatile确保多线程可见性
     */
    private static volatile ConfigurationManager instance;

    /**
     * 配置缓存，使用ConcurrentHashMap确保线程安全
     */
    private final Map<String, Object> configCache = new ConcurrentHashMap<>();

    /**
     * JWT相关配置
     */
    private JwtConfig jwt = new JwtConfig();

    /**
     * 业务配置
     */
    private BusinessConfig business = new BusinessConfig();

    /**
     * 私有构造器，防止外部直接实例化
     */
    private ConfigurationManager() {
        log.info("ConfigurationManager实例正在创建...");
    }

    /**
     * 获取单例实例 - 双重检查锁定
     * 这是经典的单例模式实现方式
     */
    public static ConfigurationManager getInstance() {
        if (instance == null) {
            synchronized (ConfigurationManager.class) {
                if (instance == null) {
                    instance = new ConfigurationManager();
                }
            }
        }
        return instance;
    }

    /**
     * Spring初始化后调用，设置单例实例
     * 实现InitializingBean接口的方法
     */
    @Override
    public void afterPropertiesSet() {
        synchronized (ConfigurationManager.class) {
            if (instance == null) {
                instance = this;
                log.info("ConfigurationManager单例实例已通过Spring容器初始化");
            }
        }
        loadDefaultConfigurations();
    }

    /**
     * 加载默认配置
     */
    private void loadDefaultConfigurations() {
        // 设置默认业务配置
        putConfig("order.timeout.minutes", 30);
        putConfig("inventory.reserve.minutes", 15);
        putConfig("payment.timeout.minutes", 5);
        putConfig("max.order.items", 20);
        putConfig("default.page.size", 10);
        
        log.info("默认配置已加载，共{}个配置项", configCache.size());
    }

    /**
     * 获取配置值
     * @param key 配置键
     * @return 配置值
     */
    public Object getConfig(String key) {
        return configCache.get(key);
    }

    /**
     * 获取配置值（带默认值）
     * @param key 配置键
     * @param defaultValue 默认值
     * @return 配置值
     */
    @SuppressWarnings("unchecked")
    public <T> T getConfig(String key, T defaultValue) {
        Object value = configCache.get(key);
        return value != null ? (T) value : defaultValue;
    }

    /**
     * 设置配置值
     * @param key 配置键
     * @param value 配置值
     */
    public void putConfig(String key, Object value) {
        configCache.put(key, value);
        log.debug("配置已更新: {} = {}", key, value);
    }

    /**
     * 删除配置
     * @param key 配置键
     */
    public void removeConfig(String key) {
        configCache.remove(key);
        log.debug("配置已删除: {}", key);
    }

    /**
     * 获取所有配置
     * @return 配置映射
     */
    public Map<String, Object> getAllConfigs() {
        return new ConcurrentHashMap<>(configCache);
    }

    /**
     * 清空所有配置
     */
    public void clearConfigs() {
        configCache.clear();
        log.info("所有配置已清空");
    }

    /**
     * 获取配置项数量
     * @return 配置项数量
     */
    public int getConfigCount() {
        return configCache.size();
    }

    /**
     * JWT配置类
     */
    @Getter
    @Setter
    public static class JwtConfig {
        private String secret = "defaultSecret";
        private long expiration = 86400000; // 24小时
        private long refreshExpiration = 604800000; // 7天
    }

    /**
     * 业务配置类
     */
    @Getter
    @Setter
    public static class BusinessConfig {
        private int orderTimeoutMinutes = 30;
        private int inventoryReserveMinutes = 15;
        private int paymentTimeoutMinutes = 5;
        private int maxOrderItems = 20;
        private int defaultPageSize = 10;
        private boolean enableCoupon = true;
        private boolean enableInventoryCheck = true;
    }

    /**
     * 防止反序列化创建新实例
     */
    private Object readResolve() {
        return getInstance();
    }

    /**
     * 重写toString方法
     */
    @Override
    public String toString() {
        return String.format("ConfigurationManager{配置项数量=%d, JWT密钥长度=%d}", 
                           configCache.size(), 
                           jwt.secret != null ? jwt.secret.length() : 0);
    }
}
